///@file SymTensor2.h
///@brief Declaration of the class representing a symetric second order tensor
///@author Arnaud Duval
///@version 0.0
///@date 2010/02/26


#ifndef SYMTENSOR2_H
#define SYMTENSOR2_H

#include <assert.h>
#include <iostream>
#include "Vector.h"
#include "Tensor2.h"

///@class SymTensor2
///@brief Class defining a second order tensor
/// A SymTensor2 derive from a Tensor2
class SymTensor2
{
	private :

	protected:
		///@brief dimension of the tensor
		unsigned int dim;
		///@brief array of vector containing the datas
		Vector *a;
	
	public :  
		///@brief Default constructor
		SymTensor2();
		///@brief Constructor giving the dimension
		SymTensor2(int);
		///@brief Constructor of a specific tensor
		SymTensor2(int, char);
		///@brief Copy constructor
		SymTensor2(const SymTensor2&);
		///@brief Copy constructor for temporary objects
		SymTensor2(SymTensor2*);
		///@brief Destructor
		~SymTensor2();
		///@brief Overload of () operator
		double& operator()(unsigned int, unsigned int);
		///@brief Overload of = operator
		SymTensor2& operator = (const SymTensor2&);
		///@brief Overload of = operator for temporary objects
		SymTensor2& operator = (SymTensor2*);
		///@brief Copies SymTensor2 without size check (use with caution)
		SymTensor2& operator &= (const SymTensor2&);
		///@brief Cast operator to Tensor2
		operator Tensor2();

		///@brief Return dimension
		int Dim();
		///@brief Return deviator part of tensor
		SymTensor2 Dev();
		///@brief Return trace of tensor
		double Trace();


		///@brief Overload of * operator : product scalar-SymTensor2
		friend SymTensor2 operator * (const double&, const SymTensor2&);
		///@brief Overload of * operator : product SymTensor2-scalar
		friend SymTensor2 operator * (const SymTensor2&, const double&);
		///@brief Overload of + operator : addition of 2 Symtensor2
		friend SymTensor2 operator + (const SymTensor2&, const SymTensor2&);
		///@brief Overload of - operator : substraction of 2 SymTensor2
		friend SymTensor2 operator - (const SymTensor2&, const SymTensor2&);
		///@brief Overload of | operator : contracted product A_ij = B_ik C_kj
		friend Tensor2 operator | (const SymTensor2&, const SymTensor2&);
		///@brief Overload of || operator : double contracted product A = B_ij C_ji
		friend double operator || (const SymTensor2&, const SymTensor2&);
		///@brief Return true if SymTensor2 exists
		friend bool operator ! (const SymTensor2& t);
		///@brief Overload of << operator
		friend std::ostream& operator<<(std::ostream &, const SymTensor2&);
		
};


#endif